/*
 *    Copyright (c) 2018-2025, proj All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * Neither the name of the proj developer nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * Author: proj
 */
package com.ykht.proj.coupon.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ykht.proj.common.core.constant.CommonConstants;
import com.ykht.proj.common.core.util.R;
import com.ykht.proj.common.security.util.SecurityUtils;
import com.ykht.proj.coupon.Enum.*;
import com.ykht.proj.coupon.entity.*;
import com.ykht.proj.coupon.mapper.*;
import com.ykht.proj.coupon.service.*;
import com.ykht.proj.coupon.vo.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 优惠券表
 *
 * @author proj code generator
 * @date 2020-11-16 17:00:20
 */
@Service
@RequiredArgsConstructor
@Slf4j
@Transactional
public class CnCouponServiceImpl extends ServiceImpl<CnCouponMapper, CnCoupon> implements CnCouponService {

	private final CnCouponMapper cnCouponMapper;

	private final CnCouponLogMapper cnCouponLogMapper;

	private final CnShopMapper cnShopMapper;

	private final CnBrandMapper cnBrandMapper;

	private final CnCouShopMapper cnCouShopMapper;
	private final CnPersonMapper cnPersonMapper;
	private final FxBrandPersonService fxBrandPersonService;
	private final FxRewardPersonService fxRewardPersonService;



	@Override
	public Page<WqqfCouponVo> wqqf(Page<WqqfCouponVo> page,WqqfCoupon req) {
		page =cnCouponMapper.wqqf(page,req);
		List<Long> logList = cnCouponLogMapper.selectList(Wrappers.lambdaQuery(CnCouponLog.class)
				.eq(CnCouponLog::getRecipientId, SecurityUtils.getPersonId()).eq(CnCouponLog::getStatus, 0))//待使用
				.stream().map(CnCouponLog::getCouponId).collect(Collectors.toList());
		page.getRecords().stream().forEach(o -> o.setUseFlag(logList.contains(o.getCouId()) ? 1 : 0));
		return page;
	}

	@Override
	public List<ShopHasCouponCount> shopHasCouponCount(Collection c) {
		return cnCouponMapper.shopHasCouponCount(c);
	}


	@Override
	@Transactional(rollbackFor = Exception.class)
	public R upOrLow(Long id) {
		try {
			CnCoupon cnCoupon = this.getById(id);
			cnCoupon.setUpdateUser(SecurityUtils.getUserId());
			cnCoupon.setUpdateTime(LocalDateTime.now());
			if (cnCoupon.getStatus().equals(StatusEnum.normal.getValue())) {
				cnCoupon.setStatus(StatusEnum.forbid.getValue());
				cnBrandMapper.updateCountreduce(cnCoupon.getBrandId());
			} else {
				if (cnCoupon.getEffectiveeEndTime() != null) {
					long l = cnCoupon.getEffectiveeEndTime().toInstant(ZoneOffset.of("+8")).toEpochMilli();
					long l1 = LocalDate.now().atStartOfDay().toInstant(ZoneOffset.of("+8")).toEpochMilli();
					if (l1 > l) {
						return R.failed("优惠券已过期");
					}
				}
				cnBrandMapper.updateCountplus(cnCoupon.getBrandId());
				cnCoupon.setStatus(StatusEnum.normal.getValue());
			}
			this.updateById(cnCoupon);
			return R.ok();
		} catch (Exception e) {
			e.printStackTrace();
			return R.failed();
		}
	}


	@Override
	public R findPage(Page page, CnCouponVo cnCouponVo) {
		List<CnCouponVo> cnCoupon = cnCouponMapper.findPage(page, cnCouponVo);
		if (cnCoupon != null && cnCoupon.size() > 0) {
			for (CnCouponVo coupon : cnCoupon) {
				//列表添加适用门店字段
				List<CnShopSimpleVo> list  = cnCouShopMapper.findShop4CouponListByCouponId(coupon.getId());
				if (list.size()==1) coupon.setShopNameType(list.get(0).getName());
				else coupon.setShopNameType("多门店");

				QueryWrapper<CnCouponLog> queryWrapper = new QueryWrapper<>();
				queryWrapper.lambda().eq(CnCouponLog::getCouponId, coupon.getId());
				coupon.setCount(cnCouponLogMapper.selectCount(queryWrapper));
				if (coupon.getDateType().equals(CouponDateEnum.days.getValue())) {
					coupon.setValidity("领取后" + coupon.getEffectiveeDay() + "天内有效");
				} else {
					DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
					coupon.setValidity(formatter.format(coupon.getEffectiveeStaTime()) + "至" + formatter.format(coupon.getEffectiveeEndTime()));
				}
				if (coupon.getType().equals(CouponEnum.single.getValue())) {
					CnCouShop cnCouShop = cnCouShopMapper.selectOne(Wrappers.lambdaQuery(CnCouShop.class)
							.eq(CnCouShop::getCouId, coupon.getId()));
					CnShop cnShop = cnShopMapper.selectById(cnCouShop.getShopId());
					coupon.setShopName(cnShop!=null?cnShop.getName():"");
				} else if (coupon.getType().equals(CouponEnum.many.getValue())) {
					Integer count = cnCouShopMapper.selectCount(Wrappers.lambdaQuery(CnCouShop.class)
							.eq(CnCouShop::getCouId, coupon.getId()));
					if (count != null && count == 1) {
						selectShop(coupon.getId(), coupon);
					} else {
						coupon.setShopName("共" + count + "家可用");
					}
				} else {
					Integer count = cnShopMapper.selectCount(Wrappers.lambdaQuery(CnShop.class)
							.eq(CnShop::getBrandId, coupon.getBrandId()));
					if (count != null && count == 1) {
						coupon.setShopName(cnShopMapper.selectOne(Wrappers.lambdaQuery(CnShop.class)
								.eq(CnShop::getBrandId, coupon.getBrandId())).getName());
					} else {
						coupon.setShopName("共" + count + "家可用");
					}
				}
			}
		}
		return R.ok(page.setRecords(cnCoupon));
	}

	@Override
	public R getShop(Long brandId) {
		QueryWrapper<CnShop> queryWrapper = new QueryWrapper<>();
		queryWrapper.lambda().eq(CnShop::getBrandId, brandId);
		List<CnShop> cnShops = cnShopMapper.selectList(queryWrapper);
		return R.ok(cnShops);
	}

	@Override
	public R insertCnCoupon(CnCouponVo cnCouponVo) {
		try {
			Integer userType = SecurityUtils.getUser().getUserType();
			if (userType.equals(UserTypeEnum.shop.getValue())) {
				cnCouponVo.setType(CouponEnum.single.getValue());
				CnShop cnShops = cnShopMapper.selectById(SecurityUtils.getSjId());
				cnCouponVo.setBrandId(cnShops.getBrandId());
				cnCouponVo.setCompanyId(cnShops.getCompanyId());
				List<Long> list = new ArrayList<>();
				list.add(cnShops.getId());
				cnCouponVo.setShopIds(list);
			}else{
				cnCouponVo.setCompanyId(cnBrandMapper.selectById(cnCouponVo.getBrandId()).getCompanyId());
			}
			CnCoupon coupon = BeanUtil.toBean(cnCouponVo, CnCoupon.class);
			coupon.setCreateUser(SecurityUtils.getUserId());
			coupon.setCreateTime(LocalDateTime.now());
			cnCouponMapper.insert(coupon);
			if (cnCouponVo.getType().equals(CouponEnum.many.getValue()) || cnCouponVo.getType().equals(CouponEnum.single.getValue())) {
				List<Long> shopIds = cnCouponVo.getShopIds();
				shopIds.forEach(Ids -> {
					CnCouShop cnCouShop = new CnCouShop();
					cnCouShop.setCouId(coupon.getId());
					cnCouShop.setShopId(Ids);
					cnCouShop.setCreateTime(LocalDateTime.now());
					cnCouShop.setCreateUser(SecurityUtils.getUserId());
					cnCouShopMapper.insert(cnCouShop);
				});
			}
			if (cnCouponVo.getType().equals(CouponEnum.currency.getValue())) {
				cnBrandMapper.updateCountplus(cnCouponVo.getBrandId());
			}
			return R.ok();
		} catch (Exception e) {
			e.printStackTrace();
			return R.failed();
		}
	}


	@Override
	public R getBrand() {
		Long userId = SecurityUtils.getUserId();
		List<CnBrand> cnBrands = cnBrandMapper.selectList(Wrappers.lambdaQuery(CnBrand.class)
				.eq(CnBrand::getLoginId, userId));
		return R.ok(cnBrands);
	}

	@Override
	public List<RecommendCouponVo> recommendCouponList(List<CnBrand> brandList, CnShop cnShop) {

		return cnCouponMapper.recommendCouponList(brandList, cnShop);
	}

	@Override
	@Transactional
	public R receiveCouponByIds(String ids, Long waiterId, Long articleId, Integer addCouponFlag, Long shareId) {

		List<String> list = Arrays.asList(ids.split(","));
		R r = R.ok();
		if (waiterId == null||shareId != null){
			list.stream().forEach(id->{
				this.receiveCoupon(Long.parseLong(id),null, shareId);
			});
		}else {
			r = this.receiveCouponByIds4Share(list,waiterId,articleId,addCouponFlag,shareId);
		}
		return r;
	}
	@Transactional
	R receiveCouponByIds4Share(List<String> list, Long waiterId, Long articleId, Integer addCouponFlag, Long shareId) {

		R r = this.checkCouponAndPerson(list);
		if (r.getCode()==CommonConstants.FAIL) return r;
//		r = this.receiveCouponByIds4Share(list,waiterId,articleId);

		CnPerson cnPerson = cnPersonMapper.selectById(SecurityUtils.getPersonId());
		if (0!=cnPerson.getAuthBaseStatus()) return R.failed("未授权微信基础信息");
		Integer inviteType = 0;

		FxBrandPerson fxBrandPerson = fxBrandPersonService.inviteFY(inviteType,waiterId,articleId);

		Long fyId = fxBrandPerson.getId();

		list.stream().forEach(id->{
			CnCouponLog cnCouponLog = new CnCouponLog();
			cnCouponLog.setFyId(fyId);
			cnCouponLog.setWaiterId(waiterId);
			cnCouponLog.setArticleId(articleId);
			this.receiveCoupon(Long.parseLong(id),cnCouponLog, shareId);
		});
		return R.ok();
	}


	@Override
	public R checkCouponAndPerson(List<String> list) {
		Long loginId = SecurityUtils.getPersonId();
		//判断手机号是否授权
		CnPerson cnPerson = cnPersonMapper.selectById(loginId);
		if (0!=cnPerson.getAuthBaseStatus()) return R.failed("未授权微信基础信息");

		List<CnCoupon> cnCouponList = cnCouponMapper.selectList(Wrappers.lambdaQuery(CnCoupon.class).in(CnCoupon::getId,list).ne(CnCoupon::getStatus,0));
		if (cnCouponList.size()>0) return R.failed(cnCouponList.get(0).getName()+"优惠券已下架");

		//业务要求：判断此优惠券有没有领过，如果  最后一次领取的该券已经使用则可以再次领取，其他则不可以
		List<CnCouponLog> tempCouPonLogList = cnCouponLogMapper.selectList(Wrappers.lambdaQuery(CnCouponLog.class)
				.in(CnCouponLog::getCouponId, list)
				.eq(CnCouponLog::getRecipientId, loginId)
				.eq(CnCouponLog::getStatus, 0)//未使用
		);
		if (tempCouPonLogList.size() > 0) {
			CnCoupon temp  = cnCouponMapper.selectById(tempCouPonLogList.get(0).getCouponId());
			return R.failed("不符合再次领取条件："+temp.getName()+"该券已领取过");
		}
		return R.ok();
	}

	@Override
	public Object getCouponByShopName(CnCouponVo cnCouponVo) {
		String s = cnShopMapper.getShopByBrandId(cnCouponVo.getBrandId());
		List<CnCouponVo> couponByShopName = this.baseMapper.getCouponByShopName(cnCouponVo);
		for (CnCouponVo couponVo : couponByShopName) {
			if(couponVo.getType().equals(0)){
				couponVo.setShopNameList(s);
			}
		}

		return this.baseMapper.getCouponByShopName(cnCouponVo);
	}


	@Override
	@Transactional(rollbackFor = Exception.class)
	public R receiveCoupon(Long id, CnCouponLog cnCouponLog, Long shareId) {
		Long loginId = SecurityUtils.getPersonId();
		//判断手机号是否授权
		CnPerson cnPerson = cnPersonMapper.selectById(loginId);
		if (0 != cnPerson.getAuthBaseStatus()) return R.failed("未授权微信基础信息");

		CnCoupon cnCoupon = cnCouponMapper.selectById(id);
		if (null == cnCoupon) return R.failed("优惠券不存在");
		if (0 != cnCoupon.getStatus()) return R.failed("优惠券已下架");

		//业务要求：判断此优惠券有没有领过，如果  最后一次领取的该券已经使用则可以再次领取，其他则不可以
		List<CnCouponLog> tempCouPonLogList = cnCouponLogMapper.selectList(Wrappers.lambdaQuery(CnCouponLog.class)
				.eq(CnCouponLog::getCouponId, id)
				.eq(CnCouponLog::getRecipientId, loginId)
				.eq(CnCouponLog::getStatus, 0)//未使用
		);
		if (tempCouPonLogList.size() > 0) {
			return R.failed("不符合再次领取条件：该券已领取过");
		}
		if (cnCouponLog==null) cnCouponLog = new CnCouponLog();
		cnCouponLog.setStatus(0);
		cnCouponLog.setCouponNumber(UUID.randomUUID().toString().replace("-",""));//优惠券编号
		if (CouponEnum.single.getValue().equals(cnCoupon.getType())) {
			CnCouShop cnCouShop = cnCouShopMapper.selectOne(Wrappers.lambdaQuery(CnCouShop.class).eq(CnCouShop::getCouId, id));
			//单门店才给值
			cnCouponLog.setShopId(cnCouShop.getShopId());
		}
		String verificationCode = System.currentTimeMillis() + "";
		cnCouponLog.setCouponId(id);
		cnCouponLog.setVerificationCode(verificationCode.substring(5, 13));
		cnCouponLog.setRecipientId(loginId);
		//0领取后N天内有效1时间段
		if(1==cnCoupon.getDateType()){
			cnCouponLog.setExpireTime(LocalDateTime.of(cnCoupon.getEffectiveeEndTime().getYear(),
					cnCoupon.getEffectiveeEndTime().getMonth(),
					cnCoupon.getEffectiveeEndTime().getDayOfMonth(), 23,59,59));
		}else if(0==cnCoupon.getDateType()){
			cnCouponLog.setExpireTime(LocalDateTime.now().plusDays(cnCoupon.getEffectiveeDay()));
		}
		cnCouponLog.setReceiveTime(LocalDateTime.now());
		cnCouponLog.setBrandId(cnCoupon.getBrandId());
		cnCouponLog.setCreateTime(LocalDateTime.now());
		cnCouponLog.setCreateUser(loginId);
		cnCouponLog.setCompanyId(cnCoupon.getCompanyId());
		cnCouponLogMapper.insert(cnCouponLog);

		if (CouponEnum.currency.getValue().equals(cnCoupon.getType())){
			//通用券领取数量加1
			cnBrandMapper.add1TyCouponCountByBrandId(cnCoupon.getBrandId());
		}

		log.info("------------------->shareId:{}",shareId);
		FxShare share = new FxShare().selectById(shareId);
		//c端用户分享相关shareId
		if (shareId != null && share != null && !loginId.equals(share.getPerId())){
			fxRewardPersonService.rewardByShareCoupon(share,cnCouponLog);
		}
		return R.ok(cnCouponLog.getId());
	}


	/**
	 * C端（用户） 领劵中心列表
	 *
	 * @return
	 */
	@Override
	public List<CnCouponDetailResp> getCouponList() {
		// 获取满足条件的品牌
		List<CnCoupon> cnCouponList = cnCouponMapper.getBrandId();
		if (cnCouponList.size() > 0) {
			List<Long> brandIdList = new ArrayList<>();
			cnCouponList.stream().forEach(itme -> brandIdList.add(itme.getBrandId()));
			// 查询满足条件的优惠券
			List<CnCouponDetailResp> detailRespList = cnCouponMapper.getCouponList(brandIdList, SecurityUtils.getPersonId());
			if (detailRespList.size() > 0) {
				List<CnCouponDetailResp> detailRespArrayList = new ArrayList<>();
				for (Long id : brandIdList) {
					Integer aa = 0;
					for (CnCouponDetailResp resp : detailRespList) {
						if (id.equals(resp.getBrandId()) && aa < 2) {
							++aa;
							detailRespArrayList.add(resp);
						}
					}
				}
				return detailRespArrayList;
			}
		}
		return null;
	}

	/**
	 * C端（用户） 领劵中心列表的下拉
	 *
	 * @param ids
	 * @return
	 */
	@Override
	public List<CnCouponDetailResp> getCouponListPage(List<Long> ids) {
		// 获取满足条件的品牌
		List<CnCoupon> cnCouponList = cnCouponMapper.getBrandIdPage(ids);
		if (cnCouponList.size() > 0) {
			List<Long> brandIdList = new ArrayList<>();
			cnCouponList.stream().forEach(itme -> brandIdList.add(itme.getBrandId()));
			// 查询满足条件的优惠券
			List<CnCouponDetailResp> detailRespList = cnCouponMapper.getCouponListPage(brandIdList, ids, SecurityUtils.getPersonId());
			if (detailRespList.size() > 0) {
				List<CnCouponDetailResp> detailRespArrayList = new ArrayList<>();
				for (Long id : brandIdList) {
					Integer aa = 0;
					for (CnCouponDetailResp resp : detailRespList) {
						if (id.equals(resp.getBrandId()) && aa < 2) {
							++aa;
							detailRespArrayList.add(resp);
						}
					}
				}
				return detailRespArrayList;
			}
		}
		return null;
	}

	/**
	 * 获取全部 爆款优惠 指定的数量
	 *
	 * @param number 获取几条数量
	 * @param userId 登录人ID
	 * @return
	 */
	@Override
	public List<CnCouponDetailResp> getLoginWholeHotCouponList(Integer number, List<Long> brandIdList, Long userId,List<Long> ids) {
		return cnCouponMapper.getLoginWholeHotCouponList(number, brandIdList, userId,ids);
	}

	/**
	 * 没有登录的 获取全部 爆款优惠 指定的数量
	 *
	 * @param number 获取几条数量
	 * @return
	 */
	@Override
	public List<CnCouponDetailResp> getWholeHotCouponList(Integer number) {
		return cnCouponMapper.getWholeHotCouponList(number);
	}


	@Override
	public List<CnCouponReceiveVo> couponListByShopIdAndBrandId(Long id, Long brandId) {
		return cnCouponMapper.couponListByShopIdAndBrandId(id, brandId);
	}


	public void selectShop(Long id, CnCouponVo cnCouponVo) {
		CnCouShop cnCouShop = cnCouShopMapper.selectOne(Wrappers.lambdaQuery(CnCouShop.class)
				.eq(CnCouShop::getCouId, id));
		if (cnCouponVo!=null){
			CnShop cnShop= cnShopMapper.selectById(cnCouShop.getShopId());
			if (cnShop!=null){
				cnCouponVo.setShopName(cnShop.getName());
			}

		}
	}
}
